<template>
	<view class="y-flex-1">
		<com-list
		ref="list"
		:bounce="bounce"
		:back-top-show="backTopShow"
		:refreshImage="refreshImage"
		:pulldownable="pulldownable"
		enable-scroll-event
		class="y-flex-1"
		@scroll="handleScroll"
		@pulldown="handlePulldown"
		@loadmore="handleLoadmore">
			<slot name="top"></slot>
			<cell v-for="component in components">
				<component
				v-if="component.data || component.name == 'search-input'"
				:data="component.data"
				:is="'find-' + component.name"
				:options="component.style"
				:bgColor="boxBgColor"
				:style="component.style.margin"></component>
			</cell>
			<slot name="center"></slot>
			<cell v-if="showTopGap">
				<com-gap :height="cellGap"></com-gap>
			</cell>
			<cell v-for="(grid, i) in Math.ceil(cells.length / cellColumn)" :key="i">
				<com-grid :data="cells.slice(i * cellColumn, (i + 1) * cellColumn)"
				:column="cellColumn"
				:count="cellColumn"
				:style="{'margin-left':  _pixelunit(marginGap), 'margin-right':  _pixelunit(marginGap), 'margin-bottom': _pixelunit(cellGap)}">
					<template v-slot="{item, index}">
						<component
						:is="'find-' + cellName"
						:options="cellStyle"
						:item="item"></component>
					</template>
				</com-grid>
			</cell>
			<cell v-if="loadmoreable || loading || (loadmore == 'end' && cells.length == 0 && components.length == 0)">
				<com-loadmore class="mt-30 mb-30" :color="loadingColor" :state="loading ? 'loading' : loadmore" @loadmore="handleLoadmore"></com-loadmore>
			</cell>
			<cell v-if="!loadmoreable">
				<com-gap></com-gap>
			</cell>
			<slot name="bottom"></slot>
			<template #backTop v-if="backTopImage">
				<image class="backTop" :src="backTopImage" mode="aspectFit"></image>
			</template>
		</com-list>
	</view>	
</template>

<script>
	import { pixelunit } from '@/assets/js/util.js'
	import FindSearchInput from './FindModule/FindSearchInput.vue'
	import FindSlider from './FindModule/FindSlider.vue'
	import FindBanner from './FindModule/FindBanner.vue'
	import FindNoticeBar from './FindModule/FindNoticeBar.vue'
	import FindMenu from './FindModule/FindMenu.vue'
	import FindLink from './FindModule/FindLink.vue'
	import FindLinks from './FindModule/FindLinks.vue'
	import FindCard from './FindModule/FindCard.vue'
	import FindHCell from './FindCell/HCell.vue'
	import FindVCell from './FindCell/VCell.vue'
	import FindImgCell from './FindCell/ImgCell.vue'
	import FindTextCell from './FindCell/TextCell.vue'
	import FindCommentCell from './FindCell/CommentCell.vue'
	import FindArticleCell from './FindCell/ArticleCell.vue'
	export default {
		inject: ['getPage', 'getBoxBgColor', 'getPageStyle', 'getQuery'],
		components:{
			FindSearchInput,
			FindSlider,
			FindBanner,
			FindNoticeBar,
			FindMenu,
			FindLink,
			FindLinks,
			FindCard,
			FindHCell,
			FindVCell,
			FindImgCell,
			FindTextCell,
			FindCommentCell,
			FindArticleCell
		},
		props: {
			data: {
				type: Array,
				default () {
					return new Array
				}
			},
			bounce: {
				type: Boolean,
				default: false
			},
			backTopShow: {
				type: Boolean,
				default: false
			},
			refreshImage: {
				type: String,
				default: ''
			},
			pulldownable: {
				type: Boolean,
				default: false
			},
			loadmoreable: {
				type: Boolean,
				default: false
			},
			backTopImage: {
				type: String,
				default: ''
			},
			loadingColor: {
				type: String,
				default: '#999'
			},
			cell: {
				type: Object,
				default () {
					return new Object
				}
			},
			marginGap: {
				type: [String, Number],
				default: 20
			},
			showTopGap: {
				type: Boolean,
				default: false
			},
			params: {
				type: Object,
				default () {
					return new Object
				}
			}
		},
		computed: {
			//路由参数
			query () {
				return this.getQuery()
			},
			app () {
				return getApp().globalData
			},
			boxBgColor () {
				return this.getBoxBgColor()
			},
			pageStyle () {
				return this.getPageStyle()
			},
			network () {
				return this.$store.getters['network/GET']
			},
			cellStyle () {
				return this.cell?.style || {}
			},
			cellName () {
				return this.cellStyle.cellName || 'h-cell'
			},
			cellColumn () {
				return this.cellStyle.cellColumn || 1
			},
			cellGap () {
				return typeof this.cellStyle.cellGap == 'number' ? this.cellStyle.cellGap : 30
			}
		},
		data () {
			return {
				components: [],
				cells: [],
				loading: false,
				paramsRecord: {},
				loadmore: '',
				page: 1,
				nextUrl: ''
			}
		},
		methods: {
			_pixelunit (size) {
				return pixelunit(size)
			},
			handleScroll (e) {
				this.$emit('scroll', e)
			},
			handlePulldown (callback) {
				this.$emit('pulldown', callback)
			},
			pulldownSuccess () {
				this.$refs.list && this.$refs.list.pulldownSuccess()
			},
			resetLoadmore() {
			    this.$refs.list && this.$refs.list.resetLoadmore()
			},
			backTop () {
				 this.$refs.list && this.$refs.list.backTop()
			},
			async initModule (callback, force = false) {
				try{
					this.loading = true
					if ( force || JSON.stringify(this.params) != JSON.stringify(this.paramsRecord) || (this.components.length == 0 && this.data?.length > 0) || this.cells.length == 0 && ((this.cell?.request && this.cell?.dynamicData) || (this.cell?.staticData && this.cell?.staticData.length > 0) ) ) {
						this.paramsRecord = this.app.$utils.deepClone(this.params)
						this.$refs.list && this.$refs.list.backTop(false)
						this.components = []
						this.cells = []
						await this.initComponent()
						await this.initCell(callback)
					}
					this.$emit('loaded', true)
					this.loading = false
				}catch(e){
					this.$emit('loaded', true)
					this.loading = false
					callback && callback('fail')
				}
			},
			async initComponent () {
				const components = this.data ? this.app.$utils.deepClone(this.data) : []
				for ( let i = 0; i < components.length; i++ ) {
					components[i].style = components[i].style || {}
					components[i].style.margin = this.handleMarginStyle(components[i].style)
					components[i].style.borderRadius = components[i].style.borderRadius || this.pageStyle.componentBorderRadius
					components[i].style.themeColor = this.pageStyle.themeColor
					const request = components[i].request
					const params = Object.assign({}, this.query, this.params)
					const newRequest = request ? this.network.requestHandle(request, params) : null//处理rquest请求
					const response = newRequest ? await this.network.$request(newRequest) : null//获取内容
					const moreUrl = components[i].style.moreUrl || ''
					if ( moreUrl && response ) components[i].style.moreUrl = await this.network.$text(moreUrl, response)//处理动态moreUrl
					const staticData = components[i].staticData
					const dynamicData = components[i].dynamicData
					if ( staticData ) components[i].data = this.network.staticDataHandle(staticData, Object.assign({}, params, {routeUrl: null}))
					if ( dynamicData && response ) {
						try{
							if ( dynamicData.subsection ) {
								const subsection = await this.network.$list(dynamicData.subsection, response)
								if ( staticData.subsection && staticData.subsection.length ) components[i].data.subsection = staticData.subsection.concat(subsection)
								else components[i].data.subsection = subsection
							}
							if ( dynamicData.list && this.app.$utils.typeCall(dynamicData.list) == 'Array' ) {
								const list = new Array(dynamicData.list.length)
								for ( let j = 0; j < list.length; j++ ) list[j] = await this.network.$list(dynamicData.list[j], response)
								if ( staticData.list && staticData.list.length ) components[i].data.list = staticData.list.concat(list)
								else components[i].data.list = list
							}
							if ( !dynamicData.subsection && (!dynamicData.list || this.app.$utils.typeCall(dynamicData.list) == 'String') ) {
								const data = await this.network.$list(dynamicData, response)
								if ( this.app.$utils.typeCall(staticData) == 'Array' ) components[i].data = staticData.concat(data)
								else if ( this.app.$utils.typeCall(staticData) == 'Object' ) components[i].data = Object.assign({}, staticData, data)
								else components[i].data = data
							}
						}catch(e){
							continue
						}
					}
				}
				this.components = components
			},
			handleMarginStyle (style) {
				const margin = style.margin || ''
				const arr = margin ? margin.toString().split(' ') : []
				const marginTop = style.marginTop || arr[0] || 30
				const marginBottom = style.marginBottom || arr[2] || arr[0] || 0
				const marginLeft = style.marginLeft || arr[3] || arr[0] || this.pageStyle.pageMarginGap
				const marginRight = style.marginRight || arr[1] || arr[0] || this.pageStyle.pageMarginGap
				return {
					'margin-top': this.app.$utils.pixelunit(marginTop),
					'margin-bottom':this.app.$utils.pixelunit(marginBottom),
					'margin-right': this.app.$utils.pixelunit(marginRight),
					'margin-left': this.app.$utils.pixelunit(marginLeft)
				}
			},
			async initCell (callback) {
				this.page = 1
				if ( !callback ) this.loadmore = ''
				try{
					const list = await this.handleGetCells()
					this.cells = list
					callback && callback('success')
					if ( list.length == 0 ) this.loadmore = 'end'
					else this.$refs.list.resetLoadmore()
				}catch(e){
					this.cells = []
					this.loadmore = 'end'
					callback && callback('fail')
				}
			},
			async handleLoadmore () {
				if ( ['loading', 'end'].includes(this.loadmore) || !this.loadmoreable ) return
				this.loadmore = 'loading'
				this.page++
				try{
					const list = await this.handleGetCells()
					if ( !this.loadmore ) return
					const isContained = this.app.$utils.isContained(this.cells, list)
					if ( isContained || list.length == 0 ) {
						this.loadmore = 'end'
					} else {
						this.cells = this.cells.concat(list)
						this.loadmore = ''
						this.$refs.list.resetLoadmore()
					}
				}catch(e){
					this.loadmore = 'end'
				}
			},
			async handleGetCells () {
				const params = Object.assign({}, this.query, this.params, {page: this.page, list: this.cells})
				const request = this.cell.request
				const staticData = this.cell.staticData ? this.network.staticDataHandle(this.cell.staticData, params) : []
				const dynamicData = this.cell.dynamicData
				let list = []
				if ( request && dynamicData ) {
					const newRequest = this.network.requestHandle(request, params)
					const response = request ? await this.network.$request(this.nextUrl ? Object.assign({}, newRequest, {url: this.nextUrl}) : newRequest) : null
					this.nextUrl = newRequest.nextUrl ? await this.network.$text(newRequest.nextUrl, response) : ''
					if ( response ) list = await this.network.$list(dynamicData, response)
				}
				return staticData.concat(list)
			}
		}
	}
</script>

<style>
	.box {
		padding: 30rpx 30rpx 10rpx 30rpx;
		margin: 0 30rpx 30rpx 30rpx;
		border-radius: 20rpx;
	}
	.backTop {
		width: 100rpx;
		height: 100rpx;
	}
</style>
